package com.nt.train.controller;

import com.alibaba.fastjson.JSONObject;
import com.nt.train.dto.PhoneDto;
import com.nt.train.util.ServletUtils;
import com.nt.train.vo.ResultVo;
import com.nt.train.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * https://www.jb51.net/article/242412.htm
 * https://blog.csdn.net/juligang320/article/details/124969650
 * https://blog.csdn.net/TheGreatButton/article/details/107714560
 *  演示springboot请求方式
 *  SpringBoot中Controller用法及传参
 * @author hlf
 * @version 1.0
 * @date 2022/7/31 21:34
 * @Controller + @ResponseBody
 * https://blog.csdn.net/Smy_0114/article/details/122229852
 */
@RestController
//@Controller
@RequestMapping("/boot")
public class BootGetController {

    /**方式一 @Autowired注解
     * https://blog.csdn.net/juligang320/article/details/124969650
     * */
    @Autowired
    //@Resource
    private HttpServletRequest request_1;

    /** 方式二【构造器注入】 推荐优先 开发注入*/
    private final HttpServletRequest request_2;

//    public  BootController(HttpServletRequest testRequest){
//        this.testRequest = testRequest ;
//    }

    public  BootGetController(HttpServletRequest request_2){
        this.request_2 = request_2 ;
    }

    /**方式三  set注入 */
    private HttpServletRequest request_3;

    //set注入
    @Autowired
    public void setTestRequest3(HttpServletRequest request_3) {
        this.request_3 = request_3;
    }

    /*  演示1 无参演示
     * 多种Get请求访问方式  无参处理
     * @RequestMapping("/boot")
     * @RequestMapping(value = "/second", method = RequestMethod.GET)
     * 如果限定Get请求方式， 用@GetMapping 代替 @RequestMapping
     * @GetMapping("/second")
     */
    //Get请求无参：http://localhost:8080/boot/second
    @RequestMapping("/second")
    //public User second(){
    //@ResponseBody
    public User second(HttpServletRequest request,HttpServletResponse response){
        User u = new User("张胜男", 30,"女");
       // SpringUtil.ge
        return u;
    }

    //Get请求无参：http://localhost:8080/boot/ajaxSecond
    @RequestMapping(value = "/ajaxSecond", method = RequestMethod.GET)
    public ResultVo ajaxSecond(HttpServletRequest request,HttpServletResponse response){
        User u = new User("张胜男2", 32,"女");
        return ResultVo.ok(u);
    }

    //Get请求无参：http://localhost:8080/boot/ajaxSecond2
    @GetMapping("/ajaxSecond2")
    public ResultVo ajaxSecond2(HttpServletRequest request,HttpServletResponse response){
        User u = new User("张胜男3", 33,"女");
        return ResultVo.ok(u);
    }

    /**
     * http://localhost:8080/boot/testSinglePath/hangge
     * 参数直接在路径中
     * @param name
     * @return
     */
    @GetMapping("/testSinglePath/{name}")
    public String testSinglePath(@PathVariable("name") String name) {
        return "获取到的name是：" + name;
    }

    /**
     * http://localhost:8080/boot/testSingleBack?name=hangge
     * 参数跟在?号后面
     */
    @GetMapping("/testSingleBack")
    public String testSingleBack(@RequestParam("name") String name) {
        return "获取到的name是：" + name;
    }

    /**
     *http://localhost:8080/boot/testSingleError
     * 无参数报错
     * @param name
     * @return
     */
    @GetMapping("/testSingleError")
    public String testSingleError(@RequestParam("name") String name) {
        return "获取到的name是：" + name;
    }


    /**
     * http://localhost:8080/boot/testSingleMark
     * 如果没有传递参数 Controller 将会报错，我们可以使用 required = false 标注参数是非必须的。
     * @param name
     * @return
     */
    @GetMapping("/testSingleMark")
    public String testSingleMark(@RequestParam(name = "name", required = false) String name) {
        return "获取到的name是：" + name;
    }

    /**
     * http://localhost:8080/boot/testSingleDefault
     *  或者可以指定个默认值，当没有传递参数时自动使用默认值：
     * @param name
     * @return
     */
    @GetMapping("/testSingleDefault")
    public String testSingleDefault(@RequestParam(name = "name", defaultValue = "测试900") String name) {
        return "获取到的name是：" + name;
    }


    /*
      演示 2
      在请求的路径后面表示参数，多个参数之间用 & 进行连接
     * 多种Get请求访问方式  有参处理
     * @RequestMapping("/second")
     * @RequestMapping(value = "/second", method = RequestMethod.GET)
     * 如果限定Get请求方式， 用@GetMapping 代替 @RequestMapping
     * @GetMapping("/second")
     */
    //Get请求传参：http://localhost:8080/boot/ajaxThirdParam?name=zhangsan&age=20
    @GetMapping("ajaxThirdParam")
    public ResultVo ajaxThirdParam(String name,Integer age) {
        //public ResultVo ajaxThirdParam(String name,Integer age,HttpServletRequest request,HttpServletResponse response) {
        System.out.println(name);
        System.out.println(age);
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("age",age);

        /**自带工具类上下文 获取request  */
        ServletRequestAttributes servletRequestAttributes =  (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        resultMap.put("1-name",request.getParameter("name"));
        resultMap.put("1-age",request.getParameter("age"));


        /**封装自带工具类上下文 获取request  */
        HttpServletRequest testReq = ServletUtils.getRequest();
        resultMap.put("2-name",testReq.getParameter("name"));
        resultMap.put("2-age",testReq.getParameter("age"));

        /** 注入方式1  */
        resultMap.put("注入方式1 -name",request_1.getParameter("name"));
        resultMap.put("注入方式1 -age",request_1.getParameter("age"));

        /** 注入方式2  */
        resultMap.put("注入方式2-name",request_2.getParameter("name"));
        resultMap.put("注入方式2-age",request_2.getParameter("age"));

        /** 注入方式3  */
        resultMap.put("注入方式3-name",request_3.getParameter("name"));
        resultMap.put("注入方式3-age",request_3.getParameter("age"));

        // 获取请求方式: GET
//        String getMethod()

//// 获取虚拟目录(上下文目录)：虚拟路径通过在application配置当中可以配置
//// 配置：server.servlet.context-path=/aaa
//        String getContextPath()
//// 获取Servlet路径：就是获取的controller当中配置的路径
//        String getServletPath()
///// 获取请求参数： id=3
//// http://localhost:8080/aaa/test?id=3
//        String getQueryString()
//// 获取请求URI：/servletDemo/demo1
//// 上下文路径+controller当中配置的路径
//        String getRequestURI()
//// 获取完整请求路径：http://localhost:8080/aaa/test
//        String getRequestURL()
//// 获取协议及版本：HTTP/1.1
//        String getProtocol()
//// 获取客户机的IP地址：192.168.0.0
//        String getRemoteAddr()
        //request.setCharacterEncoding("UTF-8");

        //HttpServletResponse response = servletRequestAttributes.getResponse();
        return ResultVo.ok(resultMap);
    }

    //Get请求传参：http://localhost:8080/boot/ajaxThirdParam2?name=zhangsan&age=20
    @GetMapping("ajaxThirdParam2")
    public ResultVo ajaxThirdParam2(@RequestParam(required = false,defaultValue = "李四") String name,
                                    @RequestParam(required = true) Integer age) {
        System.out.println(name);
        System.out.println(age);
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("age",age);
        return ResultVo.ok(resultMap);
    }


    //  演示 2.1 在请求的路径后面表示参数，多个参数之间用 & 进行连接
    //Get请求传参：http://localhost:8080/boot/ajaxThirdNParam?name=zhangsan&age=20&gender=1
    @GetMapping("ajaxThirdNParam")
    public ResultVo ajaxThirdNParam(String name, Integer age,String gender) {
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("age",age);
        resultMap.put("gender","gender");
        return ResultVo.ok(resultMap);
    }

    /*
    演示 3 在请求的路径后面表示参数，多个参数之间用 & 进行连接
     如果参数太多，用上面的方式来写，会导致方法中的参数过多，看起来很乱
    * 所以我们也可以使用一个javaBean来接收
   */
    //Get请求传参：http://localhost:8080/boot/getParam?name=zhangsan&age=20&gender=1
    @GetMapping("getParam")
    public ResultVo getParam(User user){
        System.out.println(user);
        // 将接收到的参数直接返回
        return ResultVo.ok(user);
    }

    //Get请求传参：http://localhost:8080/boot/getParamMap?name=zhangsan&age=20&gender=1
    @GetMapping("getParamMap")
    public ResultVo getParamMap(@RequestParam(required = false) Map params){
        System.out.println(params);
        // 将接收到的参数直接返回
        return ResultVo.ok(params);
    }

    /**
     * 请求（真实请求）：http://localhost:8080/boot/getParamJson?user={"name":"jj","age":22}
     请求(转义后)：http://localhost:8080/boot/getParamJson?user=%7b%22name%22:%22jj%22,%22age%22:22%7d
     注意：引号可以不转义，只转义大括号就行
     http://localhost:8080/boot/getParamJson?user=%7b"name":"jj","age":22%7d,也可以正常请求
     * @param user
     * @return
     */
    //Get请求传参：  http://localhost:8080/boot/getParamJson?user=%7b"name":"jj","age":22%7d,
    @GetMapping("getParamJson")
    public ResultVo getParamJson(@RequestParam("user") String user){
        System.out.println(user);
        User user1 = JSONObject.parseObject(user, User.class);
        // 将接收到的参数直接返回
        return ResultVo.ok(user1);
    }


    /**
     *@PathVariable接收参数
     * @PathVaribale 获取url中的数据
     * @param id
     * @return
     */
    @GetMapping("/bootPath/{id}")
    public ResultVo getPathVariable(@PathVariable String id){
        System.out.println("id="+id);
        return ResultVo.ok(id);
    }

    /**
     *@PathVariable接收参数
     * @PathVaribale 获取url中的数据
     * @RequestMapping(value = {"/student/{id}", "/student"}, RequestMethod.GET)
     * @param id
     * @return
     */
   // @GetMapping("/bootPath2/{id}")
    @GetMapping(value={"/bootPath2/{id}","/bootPath2","/bootPath102"})
    public ResultVo getPathVariable2(@PathVariable(name="id",required = false)  String id){
        System.out.println("id="+id);
        return ResultVo.ok(id);
    }


    /**
     *@PathVariable多个接收参数
     * @param id
     * @return
     */
   // @GetMapping("/bootPath3/{id}/{name}")
    @GetMapping(value={"/bootPath3/{id}/{name}","/bootPath3/{id}"})
    public ResultVo getPathVariables(@PathVariable(required = true) String id,@PathVariable(required = false) String name){
        System.out.println("id ="+id+" name= "+name);
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("id",id);
        return ResultVo.ok(resultMap);
    }

    /**
     *@PathVariable多个接收参数
     * @param id
     * @return
     */
    //@GetMapping("/bootPath4/{id}/{name}")
    @GetMapping(value={"/bootPath4/{id}/{name}","/bootPath4/{id}"})
    public ResultVo bootPath4(@PathVariable(required = true) String id,
                              @PathVariable(required = false) String name
            ,User user){
        System.out.println("id ="+id+" name= "+name);
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("name",name);
        resultMap.put("id",id);
        resultMap.put("user",user);
        return ResultVo.ok(resultMap);
    }

    /**
     * HttpServletRequest接收参数
     * @return
     */
    @GetMapping("/getRequest")
    public ResultVo getRequest(HttpServletRequest request,HttpServletResponse response){
        String id = request.getParameter("id");
        String userName = request.getParameter("userName");
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("id",id);
        resultMap.put("userName",userName);
        resultMap.put("success","success");
        return ResultVo.ok(resultMap);
    }

    /**
     * RequestParam
     * @param params
     * @return
     */
    @GetMapping("/consumption")
   // public ResultVo getConsumption(Map params){
   // public ResultVo getConsumption(@RequestParam(required = false) Map params){
      public ResultVo getConsumption(@RequestParam Map<String, Object> params) {
        return ResultVo.ok(params);
    }

    /**
     * 接收一个数组
     * http://localhost:8080/boot/testArg?name=tom&name=james
     * @param names
     * @return
     */
    @GetMapping("/testArg")
    public String hello(@RequestParam("name") String[] names) {
        String result = "";
        for(String name:names){
            result += name + "<br>";
        }
        return result;
    }

    @RequestMapping("/addUser")
    public ResultVo addUsers(User user) {
    //public ResultVo addUsers(@RequestParam(required = false) User user) {
        return ResultVo.ok(user);
    }


    /** -------高阶get请求处理实例-------------------*/
    @RequestMapping("/addUserPrefix")
    public ResultVo addUserPrefix(@ModelAttribute("user") User user) {
        return ResultVo.ok(user);
    }

    @InitBinder("u")
    private void initBinder(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("u.");
    }

    /**
     * 指定参数前缀
     * http://localhost:8080/boot/testPrefix?u.name=tom&u.age=10
     * @param user
     * @return
     */
    @GetMapping("/testPrefix")
    public ResultVo testPrefix(@ModelAttribute("u") User user) {
        System.out.println( "name：" + user.getName() + "<br> age：" + user.getAge());
        return ResultVo.ok(user);
    }

    /**
     * 多对象接收处理
     * http://localhost:8080/boot/testMultipleObjects?name=tom&age=10&number=123456
     * @param user
     * @param phone
     * @return
     */
    @GetMapping("/testMultipleObjects")
    public ResultVo testMultipleObjects(User user, PhoneDto phone) {
        System.out.println("name：" + user.getName() + "<br> age：" + user.getAge()
                + "<br> number：" + phone.getNumber());
        Map<String,Object>  resultMap = new HashMap<>();
        resultMap.put("phone",phone);
        resultMap.put("user",user);
        return ResultVo.ok(resultMap);
    }

    /**
     * 是否支持？
     * @param jsonObject
     * @return
     */
    @GetMapping("/getJSONObject")
    public ResultVo getJSONObject(@RequestParam(required = false) JSONObject jsonObject) {
        return ResultVo.ok(jsonObject);
    }



}
